package com.hmtech.ayp.common.s3;

import cn.hutool.core.util.StrUtil;
import com.hmtech.ayp.common.s3.enums.S3ErrorEnum;
import com.hmtech.ayp.common.s3.exception.S3Exception;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * @author 闫家洪（yanjiahong@vcredit.com）
 * @since 2023/12/20
 */
public class S3Utils {
    /**
     * 根据S3对象路径获取桶名称，
     *
     * @param s3path S3对象路径，包含桶名称的key，整个key由桶名称+ "/" + key组成
     * @return S3对象路的桶名称
     */
    public static String getBucketNameFromS3path(String s3path) throws S3Exception {
        if (StrUtil.isBlank(s3path) || !s3path.contains("/")) {
            throw new S3Exception(S3ErrorEnum.S3_KEY_IS_INVALID);
        }

        String[] parts = s3path.split("/", 2);
        return parts[0];
    }

    public static String getKeyFromS3path(String s3path) throws S3Exception {
        if (StrUtil.isBlank(s3path) || !s3path.contains("/")) {
            throw new S3Exception(S3ErrorEnum.S3_KEY_IS_INVALID);
        }

        String[] parts = s3path.split("/", 2);
        return parts[1];
    }

    /**
     * 为文件路径生成对象的唯一文件名，其操作是在这个文件的纯名称后面加一个UUID，以防止重复。
     * <p>比如，路径‘/data/tmp/user_info.txt’会返回‘user_info-[UUID].txt’</p>
     *
     * @param localFilePath 本地文件路径
     * @return S3 key
     */
    public static String generateUniqueFilename(String localFilePath) {
        // 提取文件名（包含后缀）
        String fileName = new File(localFilePath).getName();

        // 分离文件名和后缀
        int dotIndex = fileName.lastIndexOf('.');
        String namePart = (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
        String extensionPart = (dotIndex == -1) ? "" : fileName.substring(dotIndex); // 包含点号

        // 在文件名后添加UUID
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        return namePart + "-" + uuid + extensionPart;
    }

    /**
     * 生成S3对象key，其结构为"/" + 【文件夹名】 + 唯一文件名
     *
     * @param uniqueFilename 唯一文件名
     * @return S3对象路径
     */
    public static String getS3KeyFromOriginalFilename(String originalFilename) {
        String uniqueFilename = generateUniqueFilename(originalFilename);
        Date date = new Date();
        // 每日分区文件夹
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        return StrUtil.format("{}/{}", df.format(date), uniqueFilename);
    }



    /**
     * 生成S3对象key，其结构为"/" + 【文件夹名】 + 唯一文件名
     *
     * @param uniqueFilename 唯一文件名
     * @return S3对象路径
     */
    public static String getS3KeyFromUniqueFilename(String uniqueFilename) {
        Date date = new Date();
        // 每日分区文件夹
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        return StrUtil.format("{}/{}", df.format(date), uniqueFilename);
    }

    /**
     * 生成S3对象路径
     *
     * @param bucketName 桶名称
     * @param key        对象key
     * @return S3对象路径
     */
    public static String getS3Path(String bucketName, String key) {
        return StrUtil.format("{}/{}", bucketName, key);
    }

    /**
     * 获取s3path或者key的原始文件名，不带bucketName，也没有UUID
     *
     * @param s3path s3path或者key
     * @return 没有bucketName和UUID的原始上传的文件名
     */
    public static String getOriginalFilename(String s3path) {
        if (StrUtil.isBlank(s3path)) {
            throw new S3Exception(S3ErrorEnum.S3_PATH_IS_BLANK);
        }
        if (s3path.contains("/")) {
            int lastSplash = s3path.lastIndexOf("/");
            s3path = s3path.substring(lastSplash + 1);
        }
        // 最后一个（-），后续就是32UUID
        int lastDash = s3path.lastIndexOf("-");
        if (lastDash == -1 || !s3path.substring(lastDash + 1).matches("^[0-9a-z]{32}.*")) {
            // 必须要有-UUID
            throw new S3Exception(S3ErrorEnum.S3_KEY_IS_INVALID);
        }
        // 最后一个（.），后续就是后缀
        int lastDot = s3path.lastIndexOf(".");
        if (lastDot == -1) {
            // 没有后缀
            return s3path.substring(0, lastDash);
        } else {
            return s3path.substring(0, lastDash) + s3path.substring(lastDot);
        }
    }
}
